#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <malloc.h>
#include <math.h>
#include "entradaSaida.h"

#define LEITURA "r"
#define APPEND "a"

void abreArquivo(FILE **arq, char *nomeArquivo, char *modo)
{
    if(((*arq) = fopen(nomeArquivo, modo)) == NULL)
    {
	printf("\n\tO arquivo %s nao pode ser aberto.\n", nomeArquivo);
	if(strcmp(modo, "r") == 0) printf("\tVerifique se o nome especificado esta correto.\n");
	exit(0);
    }
}

void fechaArquivo(FILE **file)
{
     if(fclose((*file)))
     {
       printf("\n\tO arquivo nao pode ser fechado.\n");
       exit(1);
     }
}

void limpaArquivo(char *nomeArq)
{
	FILE *file;
	abreArquivo(&file, nomeArq, "w");
	fechaArquivo(&file);
}

void gerarCodigoAutomato(char *arqSaida, char *alfabeto, char *padrao, int **matriz, int linhas, int colunas) {

	limpaArquivo(arqSaida);

	FILE *file;
	abreArquivo(&file,arqSaida,APPEND);
	int k;

	//dependências
	fprintf(file, "%s", "#include <stdio.h>");
	fprintf(file, "%s", "\n#include <stdlib.h>");
	fprintf(file, "%s", "\n#include <string.h>");

	//padrao
	fprintf(file, "\n\nchar padrao[%d] = {", colunas-1);
	for(k = 0; k < colunas-1; k++) {
		fprintf(file, "\'%c\'",padrao[k]);
		if(k+1 < colunas-1) fprintf(file, "%s", ",");
	}

	fprintf(file, "};");
	//alfabeto global
	fprintf(file, "\nchar alfabeto[%d] = {", linhas);
	for(k = 0;k < linhas; k++) {
		fprintf(file, "\'%c\'", alfabeto[k]);
		if(k+1 < linhas) fprintf(file, "%s", ",");
	}
	//fim do alfabeto global
	fprintf(file, "%s", "};");

	//matriz global
	fprintf(file, "\nint matriz[%d][%d] = {", linhas, colunas);
	int i,j;
	for(i = 0; i < linhas; i++) {
		fprintf(file, "%s", "{");
		for (j = 0; j < colunas; j++) {
			fprintf(file, "%d", matriz[i][j]);
			if (j+1 < colunas) fprintf(file, "%s", ",");
		}
		fprintf(file, "%s", "}");
		if(i+1 < linhas) fprintf(file, "%s", ",");

	}

	fprintf(file, "%s", "};");

	//funcao para obter o indice do alfabeto
	fprintf(file, "\n\nint indice(char caracter) { ");
	fprintf(file, "\n\tint i;");
	fprintf(file, "\n\tfor(i = 0; i < %d;i++) {",linhas);
	fprintf(file, "\n\t\tif(alfabeto[i] == caracter) { ");
	fprintf(file, "\n\t\t\t return i;");
	fprintf(file, "\n\t\t}");
	fprintf(file, "\n\t}");
	fprintf(file, "\n\treturn -1;");
	fprintf(file, "\n\n}");


	//funcao para abrirArquivo
	fprintf(file, "\n\n");
	fprintf(file, "void abreArquivo(FILE **arq, char *nomeArquivo, char *modo) {");
	fprintf(file, "\n\tif(((*arq) = fopen(nomeArquivo, modo)) == NULL) {");
	fprintf(file, "\n\t\tprintf(\"\\n\\tO arquivo %%s nao pode ser aberto.\\n\", nomeArquivo);");
	fprintf(file, "\n\t\tif(strcmp(modo, \"r\") == 0) printf(\"\\tVerifique se o nome especificado esta correto.\\n\");");
	fprintf(file, "\n\t\texit(0);");
	fprintf(file, "\n\t}\n");
	fprintf(file, "\n}\n");


	fprintf(file, "\nvoid fechaArquivo(FILE **file) {");
	fprintf(file, "\n\tif(fclose((*file))) {");
	fprintf(file, "\n\t\tprintf(\"\\n\\tO arquivo nao pode ser fechado.\\n\");");
	fprintf(file, "\n\t\texit(1);");
	fprintf(file, "\n\t}\n");
	fprintf(file, "\n}");

	//funcao de transicao do automato
	fprintf(file, "\n\n//funcao que recebe o caracter lido e o estado atual e retorna o proximo estado");
	fprintf(file, "\nint transicao(int caracter, int estado) { ");
	fprintf(file, "\n\n\tif(caracter == -1) return 0;");
	fprintf(file, "\n\n\treturn matriz[caracter][estado];");
	fprintf(file, "\n\n}");

	//assinatura da funcao principal
	fprintf(file, "%s", "\n\nint main(int argc, char *argv[]){\n");

	//declara o arquivo e o caracter a ser lido do arquivo
	fprintf(file,"\n\tFILE *file;");
	fprintf(file,"\n\tchar c;");

	fprintf(file, "%s", "\n\tchar *nomeArquivo = argv[1];\n");
	fprintf(file, "%s", "\n\tint estado = 0;\n");
	fprintf(file, "%s", "\n\tint i = 0;\n");
	fprintf(file, "%s", "\n\tint v = 0;\n");

	fprintf(file,"\n\tprintf(\"Padrao %%s encontrado em:\", padrao);\n");

	fprintf(file, "\n\tabreArquivo(&file, nomeArquivo, \"r\");");

	//abrindo while
	fprintf(file, "\n\twhile((c = getc(file) ) != EOF) {");
	//fprintf(file, "%s", "\n\n\twhile(texto[i] != \'\\0\') {\n"); while anterior

	//salva o estado anterior
	fprintf(file, "%s", "\n\n\t\tint estadoAnterior = estado; \n");

	fprintf(file, "%s", "\n\n\t\testado = transicao(indice(c),estado); \n");

	//abre if
	fprintf(file, "\t\tif (estado == %d) { \n", colunas-1);

	//escreve posição em que encontrou
	//da posição corrente (i+1) reduz o tamanho do padrão (colunas-1) e soma 1 para obter o índice a partir da posicao 1
	fprintf(file, "\t\t\tprintf(\"\\n%%d \",(i+1) - %d + 1 );",colunas - 1);

	//fecha if
	fprintf(file, "%s", "\n\t\t}\n");

	//abre if
	fprintf(file, "\t\tif (estadoAnterior > estado ) { \n", colunas-1);

	fprintf(file, "\t\t\tv += estadoAnterior - estado; \n", colunas-1);

	//fecha if
	fprintf(file, "%s", "\n\t\t}\n");

	fprintf(file, "%s", "\n\t\ti++;\n");

	//fechando o while
	fprintf(file, "%s", "\n\n\t}\n");

	//fechando o arquivo
	fprintf(file, "\n\tfechaArquivo(&file);");

	//escreve o numero de caracteres lidos
	fprintf(file, "%s", "\n\tprintf(\"\\n%d caracteres lidos.\",i);");

	//escreve o numero de estados que o automato voltou
	fprintf(file, "%s", "\n\tprintf(\"\\nVoltou %d estados no total.\",v);");

	//coloca linha em branco na saída do console
	fprintf(file, "%s", "\n\tprintf(\"\\n\");");

	fprintf(file, "%s","\n\treturn 0;");
	//fechando funcao principal
	fprintf(file, "%s","\n\n}");

}

